關鍵字 parameter 我們已經在上一篇看過了!但是它的功用到底是什麼?
我們先思考一個問題:下方是一個 4 bits Johnson Counter 的程式碼,那如果我們需要其他位元數的計數器,我們應該如何完成?最簡單的方式就是設計各種位元數的計數器,雖然可行,但是是一種很不明智的選擇。我們可以透過結合 parameter 這個關鍵字來彈性實作計數器。
module johnson(
input clk, rst,
input [3:0] load,
output [3:0] out
);
D_ff d3(clk, rst, load[3], ~out[0], out[3]);
D_ff d2(clk, rst, load[2], out[3], out[2]);
D_ff d1(clk, rst, load[1], out[2], out[1]);
D_ff d0(clk, rst, load[0], out[1], out[0]);
endmodule
什麼是 parameter ? 準確來說,這種型別是常數 (constant) 而不是變數。可是為什麼我們說他讓程式碼更有彈性?因為我們可以在模組實體化時,再告知這個常數的數值應為多少。舉例來說,假設我今天想要設計一個可以自訂位元數的 Johnson Counter ,我們可以這樣宣告:
module johnson(clk, rst, load, out);
parameter N = 4;
input clk, rst;
input [N-1:0] load;
output [N-1:0] out;
D_ff d0(clk, rst, load[N-1], ~out[0], out[N-1]);
genvar i;
generate
for (i=0; i<N-1; i=i+1)
D_ff d_i(clk, rst, load[i], out[i+1], out[i]);
endgenerate
endmodule
這段程式碼中所有的數字都和 parameter N 有關,包括 input, output 的宣告、迴圈執行次數等。由於我們不確定 N 的數值為何,因此我們搭配 generate loop 來產生 D 型正反器。另外, parameter N = 4
中, 4 代表的是 N 的預設值,假設之後實體化時,我們沒有特別指定 N 的數值,那麼我們會以預設值來表示 N 。
在程式設計中,我們要盡量去避免把程式碼寫死,英文成為 Hardcoded ,因此 parameter 成為很重要的關鍵字。
那要怎麼彈性的實體化模組呢?我們會在物件名稱和模組名稱中間加上 #(...)
,而括號內部就是放 parameter 對應的數值。這件事情可以透過兩種方式來完成: (為了更清楚表達,暫時先不用 Johnson Counter 的例子)
module counter (input a, b);
parameter N = 6, M = 8;
// some more code
parameter P = 0;
endmodule
counter #(5, 9, 4) ctr(a, b);
module counter (input a, b);
parameter N = 6, M = 8;
// some more code
parameter P = 0;
endmodule
counter #(.N(5), .M(8), .P(0)) ctr(a, b);
回歸 Johnson Counter ,我們會怎麼實體化模組呢?因為這個模組只夾帶一個 parameter ,因此其實更加簡單!
johnson #(5) js1(clk, rst, load, in);
johnson #(.N(6)) js2(clk, rst, load, in);